﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;

namespace ChatForum.WCF
{
    public class SOAP<TService, TContract> where TService : TContract
    {
        public static ServiceHost Host(IEnumerable<string> baseAddresses, InstanceProvider<TService> instanceProvider, bool publishMetadata)
        {
            return Host(baseAddresses.Select(ba => new Uri(ba)), instanceProvider, publishMetadata);
        }
        public static ServiceHost Host(IEnumerable<Uri> baseAddresses, InstanceProvider<TService> instanceProvider, bool publishMetadata)
        {
            //Creating Service Host with baseAddess and service contract
            ServiceHost host = new ServiceHost(typeof(TService), baseAddresses.Select(u => new Uri(u, typeof(TService).Name.ToLower())).ToArray());
            //assigning customized instance provider
            host.Description.Behaviors.Add(instanceProvider);

            foreach (string uriScheme in baseAddresses.Select(ba => ba.Scheme))
            {
                host.AddServiceEndpoint(typeof(TContract), SchemeToBindingMapper(uriScheme), "soap");
            }
            if (publishMetadata)
            {
                host.Description.Behaviors.Add(new ServiceMetadataBehavior()
                {
                    HttpGetEnabled = true,
                    MetadataExporter = new WsdlExporter() { PolicyVersion = PolicyVersion.Policy15 }
                });
                host.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpBinding(), "");
            }
            return host;
        }

        private static System.ServiceModel.Channels.Binding SchemeToBindingMapper(string uriScheme)
        {
            switch (uriScheme)
            {
                case "http":
                    return new BasicHttpBinding();
                case "https":
                    return new WSHttpBinding();
                case "net.tcp":
                    return new NetTcpBinding();
                case "net.pipe":
                    return new NetNamedPipeBinding();
                case "net.msmq":
                    return new NetMsmqBinding();
                default:
                    return null;
            }
        }
    }
}
